home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 41.zip / BS1 part 41 / Lattice C v5.02 d4.adf / examples / boxomatic.c < prev    next >
C/C++ Source or Header  |  1988-11-07  |  13KB  |  413 lines

  1. /* 
  2.    boxomatic.c    by Gregg Williams               finished 29 May 86
  3.                      BYTE Magazine
  4.                      PO Box 372
  5.                                  Hancock NH  03449
  6.  
  7.                                      Phone: 603-924-9281
  8.                                      BIX: greggw
  9.  
  10.    This program shows:
  11.                    dual playfield with bottom playfield visible "under" top
  12.                      playfield and scrolling in two dimensions
  13.  
  14.            use of the following functions: OpenLibrary,
  15.                      InitBitMap, InitView, InitVPort,
  16.                      GetColorMap, AllocRaster, BltClear, MakeVPort, MrgCop,
  17.                          LoadView, WaitTOF, FreeMemory, CloseLibrary, SetRast,
  18.                          SetAPen, RectFill, FreeRaster, FreeVPortCopLists,
  19.                          FreeCprList, FreeColorMap
  20.  
  21.    I have kept this program as simple as possible to make the workings
  22.    of a scrolling dual-playfield as obvious as possible.  I am placing
  23.    this source code in the public domain as a small repayment of the
  24.    debt I owe the many people who have similarly contributed their work
  25.    over the years.
  26.  
  27.    Please feel free to study this program, modify it, and use it as
  28.    a "skeleton" for a larger, more powerful program that needs a dual
  29.    playfield (game designers, take note).
  30.  
  31.  
  32.                                           --Gregg Williams
  33. */
  34.  
  35. #include <exec/types.h>
  36. #include <stdio.h>
  37. #include <graphics/gfx.h>
  38. #include <hardware/dmabits.h>
  39. #include <hardware/custom.h>
  40. #include <hardware/blit.h>
  41. #include <graphics/gfxmacros.h>
  42. #include <graphics/copper.h>
  43. #include <graphics/view.h>
  44. #include <graphics/rastport.h>
  45. #include <graphics/gels.h>
  46. #include <graphics/regions.h>
  47. #include <graphics/clip.h>
  48. #include <exec/exec.h>
  49. #include <graphics/text.h>
  50. #include <graphics/gfxbase.h>
  51. #include <proto/graphics.h>
  52. #include <proto/exec.h>
  53.  
  54.  
  55.  
  56. /*   An overview of Amiga graphics--what's where:
  57.  
  58.   View  (what you see on the screen, contains important Modes variables
  59.    |     for things like interlaced screen, dual playfield, and others)
  60.    |
  61.    |--(points to)
  62.    V
  63.   ViewPort1 --> ViewPort2 --> ... --> ViewPortN
  64.    |   (A ViewPort is a horizontal slice of the screen; here you specify
  65.    |  height, width, depth (determines # of colors available),
  66.    |  sprites, type of display: dual-playfield, resolution, interlace,
  67.    |  hold-and-modify, extra-halfbright)
  68.    |    (The variables DxOffset and DyOffset position the upper left 
  69.    |  corner of the viewport on the screen)
  70.    |    (If there are multiple viewports, the first one points to the
  71.    |  second, the second to the third, etc.)
  72.    |\
  73.    | \
  74.    | V
  75.    | ColorMap (establishes the colors available to this viewport)
  76.    V
  77.   RasInfo (contains RxOffset, RyOffset, which mark the pixel within 
  78.    |       the bitmap (see below) that will be positioned in the
  79.    |       upper left corner of the viewport--you can scroll the 
  80.    |       bitmap in a viewport by changing these values)
  81.    |
  82.    |     RastPort (contains info on pen colors, text info, pointers
  83.    |     /         to GelsInfo, AreaInfo (when needed)
  84.    |    /
  85.    |   /
  86.    V  V
  87.   BitMap (contains actual memory that represents an area of image;
  88.           the image can be larger than what is visible on the screen)
  89. */
  90.  
  91. #define DEPTH 3L      /* depth of playfield 1, (scrolling, on bottom) */
  92. #define WIDTH 640L    /* dimensions of playfield 1 */
  93. #define HEIGHT 400L
  94.  
  95. /* Since pf1 is behind pf2, it can be any size you want it--you could
  96.    make it a long, thin horizontal strip if you wanted to.  Just be
  97.    sure that nothing unexpected shows through the "hole" in the top pf....
  98. */
  99.  
  100. #define DEPTH2 2L    /* depth of playfield 2 (stationary, on top) */
  101. #define WIDTH2 322L  /* dimensions of playfield 2 */
  102. #define HEIGHT2 200L
  103.  
  104. #define VPWIDTH 322L   /* dimensions of the viewport */
  105. #define VPHEIGHT 200L
  106.  
  107. /* In this simple case, the view (i.e., what you see on the screen)
  108.    is made entirely from one viewport.  If the 322 number looks odd
  109.    to you, you're not alone.  I originally had WIDTH2 and VPWIDTH to
  110.    be 320, but a thin strip of pf1 showed through the right margin of
  111.    the screen.  If you can explain why you need the 322 value, please
  112.    let me know....
  113. */
  114.  
  115. #define NOT_ENOUGH_MEMORY -1000
  116.  
  117. #define PF1_BACKGD 7L
  118. #define PF2_BACKGD 1L
  119. #define PF2_FRAME  2L
  120.  
  121.  
  122. /* construct a simple display */
  123.  
  124. struct View view;
  125. struct ViewPort viewport;
  126.  
  127. /* pointer to colormap structure, dynamically allocated */
  128. struct ColorMap *cm;
  129.  
  130. struct RasInfo rasinfo, rasinfo2;
  131. struct BitMap bitmap, bitmap2;
  132. struct RastPort rastport, rastport2;
  133.  
  134. struct GfxBase *GfxBase;
  135.  
  136. /* save the pointer to the old view so we can restore it later */
  137. struct View *oldview;
  138.  
  139. USHORT colortable[]={
  140.   /*  colors 0-7, for playfield 1
  141.   clear, gold,  cyan,  cherry, brown, green, gray,  blue   */
  142.   0x000, 0xfb0, 0xccc, 0xf15,  0xa50, 0x0c5, 0x777, 0x77f,
  143.   /* colors 8-11, for playfield 2
  144.      clear, blue,  black, rose   */
  145.      0x000, 0x55f, 0x000, 0xc57,
  146.   0,0,0,0,
  147.   0,0,0,0,0,0,0,0,
  148.   0,0,0,0,0,0,0,0
  149. };
  150. /* Remember that, even though you paint into playfield 2 with brush
  151.    numbers 0-7 (actually, 0-3 in this 2-bit playfield), the computer
  152.    maps them to colors 8-15....
  153. */
  154.  
  155. UWORD *colorpalette;
  156.  
  157. /* * * * * * * * * * * * * * * * * * * * * * * * * */
  158. void draw_playfields(void);        /* declarations of functions defined later */
  159. void draw_box(LONG, LONG, LONG, LONG);
  160. void FreeMemory(void);
  161.  
  162. void _main()
  163.  
  164. {
  165.   LONG i, n;
  166.   SHORT nmax;
  167.   SHORT pf1_xmove, pf1_ymove;
  168.  
  169.   /* 'nmax' determines how long the display runs; see below */
  170.  
  171.     nmax = 10;   /* default value */
  172.  
  173.  
  174.   /* Open the graphics library.... */
  175.   GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0L);
  176.   if (GfxBase == NULL) _exit(100);
  177.  
  178.   /* Save the current view to restore it later. */
  179.   oldview = GfxBase->ActiView;
  180.  
  181.   InitView(&view);       /* initialize view */
  182.   InitVPort(&viewport);  /* init viewport */
  183.   view.ViewPort = &viewport;     /* link view into viewport */
  184.   view.Modes = DUALPF + PFBA;   /* sets dual playfield w/ pf2 on top */
  185.   viewport.Modes = DUALPF + PFBA;   /* sets dual playfield w/ pf2 on top */
  186.  
  187.   /* Init bit map (for rasinfo and rastport). */
  188.   InitBitMap(&bitmap, DEPTH, WIDTH, HEIGHT);
  189.   InitBitMap(&bitmap2, DEPTH2, WIDTH2, HEIGHT2);
  190.  
  191.   /* Establish rast.ports for playfield 1, then playfield 2. */
  192.   InitRastPort(&rastport);
  193.   rastport.BitMap = &bitmap;
  194.  
  195.   InitRastPort(&rastport2);
  196.   rastport2.BitMap = &bitmap2;
  197.  
  198.   /* Init RasInfos for playfield 1, then playfield 2. */
  199.  
  200.   rasinfo.BitMap = &bitmap;
  201.   rasinfo.RxOffset = 0;
  202.   rasinfo.RyOffset = 0;
  203.   rasinfo.Next = &rasinfo2;   /* link this RasInfo to the next one */
  204.  
  205.   rasinfo2.BitMap = &bitmap2;
  206.   rasinfo2.RxOffset = 0;
  207.   rasinfo2.RyOffset = 0;
  208.   rasinfo2.Next = NULL;
  209.  
  210.   /* Now specify critical characteristics.... */
  211.   viewport.DWidth = VPWIDTH;
  212.   viewport.DHeight = VPHEIGHT;
  213.   viewport.RasInfo = &rasinfo;
  214.  
  215.   /* Initialize the color map, which has 32 entries (sprites take up
  216.      the top 16).   */
  217.  
  218.   cm = GetColorMap(32);
  219.  
  220.   /* If no memory for color map, reclaim memory and exit. */
  221.   if (cm == NULL) {
  222.     FreeMemory();
  223.     _exit(100);
  224.   }
  225.  
  226.   /* 'colorpalette' points to the color table for this color map. */
  227.   colorpalette = (UWORD *)cm->ColorTable;
  228.   /* We initialize this color table with the values from our array. */
  229.   for(i=0; i<32; i++) {
  230.     *colorpalette++ = colortable[i];
  231.   }
  232.  
  233.   /* Copy the color table into the viewport structure. */
  234.   viewport.ColorMap = cm;
  235.  
  236.   /* Allocate space for bitmap 1, then bitmap 2. */
  237.  
  238.   for(i=0; i<DEPTH; i++) {
  239.     bitmap.Planes[i] = (PLANEPTR) AllocRaster(WIDTH, HEIGHT);
  240.         if(bitmap.Planes[i] == NULL) {
  241.         FreeMemory();
  242.         _exit(NOT_ENOUGH_MEMORY);
  243.     }
  244.         BltClear(bitmap.Planes[i], RASSIZE(WIDTH, HEIGHT), 1);
  245.   }
  246.   for(i=0; i<DEPTH2; i++) {
  247.     bitmap2.Planes[i] = (PLANEPTR) AllocRaster(WIDTH2, HEIGHT2);
  248.         if(bitmap2.Planes[i] == NULL) {
  249.         FreeMemory();
  250.         _exit(NOT_ENOUGH_MEMORY);
  251.     }
  252.         BltClear(bitmap2.Planes[i], RASSIZE(WIDTH2, HEIGHT2), 1);
  253.   }
  254.  
  255.   draw_playfields();   /* Draw desired graphics into pf1 and pf2. */
  256.  
  257.   /* These three instructions assemble and "load" the view we've defined.*/
  258.   MakeVPort(&view, &viewport);
  259.   MrgCop(&view);
  260.   LoadView(&view);
  261.  
  262.   pf1_xmove = 1; pf1_ymove = 1;
  263.  
  264.   /* This is the main loop of the program; we scroll playfield 1 (the bottom
  265.      one) by changing its 'RxOffset' and 'RyOffset' values; we change the
  266.          direction of the scrolling (both horizontally and vertically) when
  267.          each brings us near the edge of the playfield 1 bitmap.
  268.            'n' starts at 1 and increments each time there is a scrolling 
  269.      change.  This program ends when 'n' reaches the value 'nmax', which
  270.          either defaults to 10 or is specified by the user.
  271.    */
  272.  
  273.   for( n=1; n<=nmax;  )   {
  274.  
  275.           rasinfo.RxOffset = rasinfo.RxOffset + pf1_xmove;
  276.           rasinfo.RyOffset = rasinfo.RyOffset + pf1_ymove;
  277.  
  278.       if (rasinfo.RxOffset <= 0  ||  rasinfo.RxOffset >= 319)  {
  279.             pf1_xmove = -pf1_xmove;
  280.                 n = n + 1;     /* sorry, no C jargon here--code should be readable */
  281.       }
  282.       if (rasinfo.RyOffset <= 0  ||  rasinfo.RyOffset >= 199)  {
  283.             pf1_ymove = -pf1_ymove;
  284.                 n = n + 1;
  285.       }
  286.  
  287.           /* Reexecute this trio of instructions to make the changes visible. */
  288.           MakeVPort(&view, &viewport);
  289.           MrgCop(&view);
  290.           LoadView(&view);
  291.  
  292.           /* Slow it down to one move per video frame: this routine waits
  293.              until the electron gun in the video display is about to start
  294.                  drawing a new frame.   */
  295.  
  296.           WaitTOF();
  297.   }   /* end of 'for' loop */
  298.  
  299.   /* Restore the system to its original state. */
  300.   LoadView(oldview);
  301.  
  302.   /* The two statements that follow return the memory allocated by
  303.      this program to the system for general use.  If you do not do
  304.          this, you lose access to a big chunk of memory each time you
  305.          run this program and, eventually, the Amiga refuses to work
  306.          properly for lack of available memory.   */
  307.  
  308.   FreeMemory();
  309.   CloseLibrary((struct Library *)GfxBase);
  310.  
  311. }     /* end of main() */
  312.  
  313. /* * * * * * * * * * * * * * * * * * * * * * * * * * * */
  314.  
  315. void draw_playfields()
  316. /* This routine draws playfields 1 and 2 for later display. */
  317. {
  318.   LONG x, y, temp, color1, color2;
  319.  
  320.   /* Draw "window" of playfield 2 (the stationary one on top). */
  321.  
  322.   SetRast( &rastport2, PF2_BACKGD );   /* flood raster with backgd color */
  323.  
  324.   SetAPen( &rastport2, PF2_FRAME );  /* this is the color of the "frame" */
  325.   RectFill( &rastport2, 95L, 45L, 225L, 155L );
  326.  
  327.   SetAPen( &rastport2, 0);    /* this is the "transparent" window (color
  328.                                  0) that allows us to see through to
  329.                                  the lower playfield (pf1)         */
  330.   RectFill( &rastport2, 100L, 50L, 220L, 150L );
  331.  
  332.   /*  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  */
  333.   /* Draw the boxes in playfield 1 (the scrolling one on bottom). */
  334.  
  335.   SetRast( &rastport, PF1_BACKGD );
  336.  
  337.   temp = 1L;
  338.   for( x=25L; x<=590L; x=x+50L )   {
  339.  
  340.     for ( y=0L; y<=350L; y=y+50L)   {
  341.  
  342.           color1 = temp;     /* this code simply generates an ever-changing
  343.                                 set of color pairs for draw_box */
  344.           temp = temp + 1L;
  345.           if (temp > 7L) temp = 1L;
  346.           color2 = temp;
  347.           temp = temp + 1L;
  348.           if (temp > 7L) temp = 1L;
  349.  
  350.           /* Draw a box given its position and two colors. */
  351.           draw_box( x, y, color1, color2 );
  352.         }
  353.   }   /* end outer 'for' loop */
  354.  
  355. }   /* end draw_playfields */
  356.  
  357. /* * * * * * * * * * * * * * * * * * * * * * * * * * * */
  358.  
  359. void draw_box( x, y, bigsq_color, smallsq_color )
  360. /*
  361.    This function draws a boxlike design onto pf1 at row x, column y;
  362.    bigsq_color and smallsq_color are the color numbers used to draw
  363.    the double box.   */
  364.  
  365. LONG x, y, bigsq_color, smallsq_color;
  366.  
  367. {
  368.    SetAPen( &rastport, 0 );   /* draw black shadow */
  369.    RectFill( &rastport, x+4L, y+4L, x+40L, y+40L );
  370.  
  371.    SetAPen( &rastport, 0 );   /* draw large black box */
  372.    RectFill( &rastport, x, y, x+36L, y+36L );
  373.  
  374.    SetAPen( &rastport, bigsq_color );   /* draw large colored box */
  375.    RectFill( &rastport, x+2L, y+2L, x+34L, y+34L );
  376.  
  377.    SetAPen( &rastport, smallsq_color );   /* draw small colored box */
  378.    RectFill( &rastport, x+12L, y+12L, x+24L, y+24L );
  379.  
  380. }   /* end draw_box */
  381.  
  382. /* * * * * * * * * * * * * * * * * * * * * * * * * * * */
  383.  
  384. void FreeMemory()
  385. /* Return user and system-allocated memory to the system. */
  386. {
  387.   LONG i;
  388.  
  389.   /* Free both bitmaps. */
  390.   for (i=0; i<DEPTH; i++) {
  391.         if (bitmap.Planes[i] != NULL) {
  392.       FreeRaster(bitmap.Planes[i], WIDTH, HEIGHT);
  393.         }
  394.   }
  395.   for (i=0; i<DEPTH2; i++) {
  396.         if (bitmap2.Planes[i] != NULL) {
  397.       FreeRaster(bitmap2.Planes[i], WIDTH2, HEIGHT2);
  398.         }
  399.   }
  400.  
  401.   /* free the color map created by GetColorMap() */
  402.   if (cm != NULL)  FreeColorMap(cm);
  403.  
  404.   /* Free some other dynamically created structures. */
  405.   FreeVPortCopLists(&viewport);
  406.   FreeCprList(view.LOFCprList);
  407.  
  408. }   /* end FreeMemory */
  409.  
  410. /*---end---of---boxomatic.c---*/
  411.  
  412. /*  (pant, pant, pant) ...and this was a *simple* program... (sigh) */
  413.